/**
 *
 */
package org.geoserver.jtilecache.tile;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;

import java.io.InputStream;
import java.io.Serializable;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geoserver.jtilecache.mime.ImageMimeType;

/**
 * @author Chris Whitney
 *
 */
public class ImageTile implements Serializable {

	/**
	 * @serial
	 */
	private static final long serialVersionUID = -5171595780192211808L;


	private static Log log = LogFactory.getLog(org.geoserver.jtilecache.tile.ImageTile.class);

	// Store the image  in memory
	private BufferedImage img = null;

	// Keep a reference to the parent layer
	private Layer layer = null;


	public ImageTile(Layer layer) {

		this.layer = layer;

		if(log.isTraceEnabled()) log.trace(this.toString());
	}

	public ImageTile(Layer layer, InputStream in) throws IOException {
		this.layer = layer;
		this.read(in);
		if(log.isTraceEnabled()) log.trace(this.toString());
	}

	public BufferedImage getBufferedImage() {
		return this.img;
	}

	public void setBufferedImage(BufferedImage img) {
		this.img = img;
		if(log.isTraceEnabled()) log.trace("Set image to: " + this.img);
	}

	/**
	 * @return the layer
	 */
	public Layer getLayer() {
		return layer;
	}

	/**
	 * @param layer the layer to set
	 */
	public void setLayer(Layer layer) {
		this.layer = layer;
	}

	/**
	 * @return the height of the image tile
	 */
	public int getHeight() {
		return this.layer.getImageFormat().getHeight();
	}

	/**
	 * @return the width of the image tile
	 */
	public int getWidth() {
		return this.layer.getImageFormat().getWidth();
	}

	public ImageMimeType getMime() {
		return this.layer.getImageFormat().getMime();
	}

	public void read(InputStream in) throws IOException {
		try {
			this.img = ImageIO.read(in);
		} catch(IOException ioe) {
			if(log.isErrorEnabled()) log.error("Error converting stream to image: ", ioe);
			throw ioe;
		}
	}

	public boolean write(OutputStream out) throws IOException {
		boolean rtrn = false;
		ImageMimeType mime = this.layer.getImageFormat().getMime();
		try {
			rtrn = ImageIO.write((RenderedImage)img, mime.getFormat(), out);
			if(log.isDebugEnabled()) log.debug("Wrote to output stream using MIME type: " + mime.getFormat() + ".");
		} catch (IOException ioe) {
			if(log.isErrorEnabled()) log.error("Cannot write to OutputStream: ", ioe);
			throw ioe;
		}
		return rtrn;
	}

	public boolean write(OutputStream out, ImageMimeType mime) throws IOException {
		boolean rtrn = false;
		try {
			rtrn = ImageIO.write((RenderedImage)img, mime.getFormat(), out);

			// Immediately flush all output
			out.flush();

			if(log.isDebugEnabled()) log.debug("Wrote to output stream using MIME type: " + mime.getFormat() + ".");
		} catch (IOException ioe) {
			if(log.isErrorEnabled()) log.error("Cannot write to OutputStream: ", ioe);
			throw ioe;
		}
		return rtrn;
	}

	public String toString() {
		String rtrn = "Image: " + this.img.toString() + "; ";
		return rtrn;
	}

}
